package com.woniuxy.health.commodity.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.health.aspect.OperationLogAnnotation;
import com.woniuxy.health.commodity.annotation.Idempotent;
import com.woniuxy.health.commodity.annotation.UpdateBookESAnnotation;
import com.woniuxy.health.commodity.constant.Constant;
import com.woniuxy.health.commodity.dto.Goods4AddDTO;
import com.woniuxy.health.commodity.dto.GoodsDTO;
import com.woniuxy.health.model.commodity.Goods;
import com.woniuxy.health.oss.OSSUtil;
import com.woniuxy.health.vo.PageVO;
import com.woniuxy.utils.result.Result;
import com.woniuxy.utils.result.ResultCodeEnum;
import com.woniuxy.utils.result.handle.WoniuHealthException;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import com.woniuxy.health.commodity.service.IGoodsService;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author woniuxy
 * @since 2023-09-04
 */
@RestController
@RequestMapping("/goods")
public class GoodsController {

    private final IGoodsService goodsServiceImpl;
    private final RedisTemplate redisTemplate;
    private final OSSUtil ossUtil;

    public GoodsController(IGoodsService goodsServiceImpl, RedisTemplate redisTemplate, OSSUtil ossUtil){
        this.goodsServiceImpl = goodsServiceImpl;
        this.redisTemplate = redisTemplate;
        this.ossUtil = ossUtil;
    }

    // 添加商品
    @OperationLogAnnotation(module = "商品列表", type = "新增", description = "新增一条商品")
    @Idempotent(expireTime = 30, timeunit = TimeUnit.SECONDS)
    @UpdateBookESAnnotation
    @PostMapping("/add")
    @ApiOperation("添加商品")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "js", value = "文件对象"),
                    @ApiImplicitParam(name = "fileList", value = "图片文件列表")
            }
    )
    public Result add(@RequestParam String js,
                      @RequestParam("fileList") MultipartFile[] files){
        Goods4AddDTO goods4AddDTO = JSONUtil.toBean(js, Goods4AddDTO.class);

        String bigPhoto = "";
        for (MultipartFile file : files) {
            try {
                String fileName = file.getOriginalFilename();
                String uuidFileName = ossUtil.generateUUIDFileName(fileName);
                String key = "imgs/" + uuidFileName; // 设置文件在OSS中的存储路径
                ossUtil.uploadFile(key, file.getInputStream());
                bigPhoto += key + ";"; // 返回文件在OSS中的存储路径
            } catch (Exception e) {
                throw new WoniuHealthException(ResultCodeEnum.FAIL);
            }
        }
        Goods goods = new Goods();
        BeanUtil.copyProperties(goods4AddDTO, goods);
        goods.setBigPhoto(bigPhoto);
        goodsServiceImpl.save(goods);
        return Result.ok();
    }

    // es查询
    @PostMapping("/esSearch")
    @ApiOperation("es查询")
    @ApiImplicitParam(name = "goodsDTO", value = "查询对象")
    public Result esSearch(@RequestBody GoodsDTO goodsDTO) throws ExecutionException, InterruptedException {

//        Callable<PageVO> pageVOCallable = new Callable<PageVO>() {
//            @Override
//            public PageVO call() throws Exception {
//                Pageable page = PageRequest.of(goodsDTO.getPageNum() - 1, goodsDTO.getPageSize());
//                PageVO pageVO = goodsServiceImpl.listByElasticSearch(page, goodsDTO);
//                return pageVO;
//            }
//        };
//
//        FutureTask<PageVO> ft =
//                new FutureTask<>(pageVOCallable);
//
//        Thread thread = new Thread(ft);
//        thread.start();
//        PageVO pageVO = ft.get();

        Pageable page = PageRequest.of(goodsDTO.getPageNum() - 1, goodsDTO.getPageSize());
        PageVO pageVO = goodsServiceImpl.listByElasticSearch(page, goodsDTO);
        return Result.ok(pageVO);
    }

    // 批量删除
    @UpdateBookESAnnotation
    @PostMapping("/batchDelete")
    @ApiOperation("批量删除")
    @ApiImplicitParam(name = "list", value = "批量删除id集合")
    public Result batchDelete(@RequestBody List<Integer> list){
        goodsServiceImpl.removeBatchByIds(list);
        return Result.ok();
    }

    // 上架
    @UpdateBookESAnnotation
    @PostMapping("/batchUpload")
    @ApiOperation("上架")
    @ApiImplicitParam(name = "ids", value = "批量上架id集合")
    public Result batchUpload(@RequestBody List<Integer> ids){
        goodsServiceImpl.batchOperate(ids, (byte) 0);
        return Result.ok();
    }

    // 下架
    @UpdateBookESAnnotation
    @PostMapping("/batchRemove")
    @ApiOperation("下架")
    @ApiImplicitParam(name = "ids", value = "批量下架id集合")
    public Result batchRemove(@RequestBody List<Integer> ids){
        goodsServiceImpl.batchOperate(ids, (byte) 1);
        return Result.ok();
    }

    @PostMapping("/getPageInfo")
    @ApiOperation("查询分页信息")
    @ApiImplicitParam(name = "goodsDTO", value = "分页查询对象")
    public Result getPageInfo(@RequestBody GoodsDTO goodsDTO){
        Page pageInfo = goodsServiceImpl.getPageInfo(goodsDTO);
        return Result.ok(pageInfo);
    }

    @UpdateBookESAnnotation
    @DeleteMapping("/delete/{id}")
    @ApiOperation("删除单个商品")
    @ApiImplicitParam(name = "id", value = "商品id")
    public Result delete(@PathVariable("id") Integer id){

        if (redisTemplate.hasKey(Constant.INTERFACE_IDEA_PREFIX + id)){
            return Result.fail(ResultCodeEnum.HTTP_ALREADY_HANDLE);
        }
        redisTemplate.opsForValue()
                .setIfAbsent(Constant.INTERFACE_IDEA_PREFIX + id, "",
                        30, TimeUnit.SECONDS);

        goodsServiceImpl.removeById(id);
        return Result.ok();
    }

    @UpdateBookESAnnotation
    @PutMapping("/update")
    @ApiOperation("更新商品")
    @ApiImplicitParam(name = "goods", value = "更新商品对象")
    public Result update(@RequestBody Goods goods){
        goodsServiceImpl.updateById(goods);
        return Result.ok();
    }
}
